/**
 * 公式计算器
 * 用于工程质量检测参数配置中的计算表达式验证和计算
 */
class FormulaCalculator {
  constructor() {
    this.functions = {
      // ==================== 基础数学函数 ====================
      
      /**
       * 四舍五入到指定精度
       * @param {number} value - 要舍入的值
       * @param {number} precision - 小数位数
       * @returns {number} 舍入后的值
       */
      ROUND: (value, precision) => {
        const factor = Math.pow(10, precision);
        return Math.round(value * factor) / factor;
      },

      /**
       * 求和函数
       * @param {...number} args - 要相加的数值
       * @returns {number} 所有参数的和
       */
      SUM: (...args) => args.reduce((sum, val) => sum + (Number(val) || 0), 0),

      /**
       * 计算平均值
       * @param {...number} args - 要计算平均的数值
       * @returns {number} 所有参数的平均值
       */
      AVG: (...args) => {
        const validArgs = args.filter(arg => !isNaN(Number(arg)) && arg !== null && arg !== undefined);
        return validArgs.length ? this.functions.SUM(...validArgs) / validArgs.length : 0;
      },

      /**
       * 求最大值
       * @param {...number} args - 要比较的数值
       * @returns {number} 所有参数中的最大值
       */
      MAX: (...args) => Math.max(...args.map(arg => Number(arg) || -Infinity)),

      /**
       * 求最小值
       * @param {...number} args - 要比较的数值
       * @returns {number} 所有参数中的最小值
       */
      MIN: (...args) => Math.min(...args.map(arg => Number(arg) || Infinity)),

      /**
       * 求绝对值
       * @param {number} value - 要求绝对值的数值
       * @returns {number} 绝对值
       */
      ABS: (value) => Math.abs(Number(value) || 0),

      /**
       * 求平方根
       * @param {number} value - 要求平方根的数值
       * @returns {number} 平方根
       */
      SQRT: (value) => Math.sqrt(Math.max(0, Number(value) || 0)),

      /**
       * 幂运算
       * @param {number} base - 底数
       * @param {number} exponent - 指数
       * @returns {number} 幂运算结果
       */
      POW: (base, exponent) => Math.pow(Number(base) || 0, Number(exponent) || 0),
      
      // ==================== 逻辑判断函数 ====================
      
      /**
       * IF条件判断函数
       * @param {boolean} condition - 条件表达式
       * @param {any} valueIfTrue - 条件为真时的返回值
       * @param {any} valueIfFalse - 条件为假时的返回值
       * @returns {any} 根据条件返回的值
       */
      IF: (condition, valueIfTrue, valueIfFalse) => {
        // 处理各种类型的条件值
        let boolCondition = false;
        
        if (typeof condition === 'boolean') {
          boolCondition = condition;
        } else if (typeof condition === 'number') {
          boolCondition = condition !== 0 && !isNaN(condition);
        } else if (typeof condition === 'string') {
          // 字符串转布尔值
          const lowerStr = condition.toLowerCase().trim();
          boolCondition = !(lowerStr === 'false' || lowerStr === '0' || lowerStr === '' || lowerStr === 'null' || lowerStr === 'undefined');
        } else {
          boolCondition = Boolean(condition);
        }
        
        return boolCondition ? valueIfTrue : valueIfFalse;
      },

      /**
       * AND逻辑与运算
       * @param {...boolean} args - 多个条件表达式
       * @returns {boolean} 所有条件都为真时返回true
       */
      AND: (...args) => {
        return args.every(arg => {
          if (typeof arg === 'boolean') return arg;
          if (typeof arg === 'number') return arg !== 0 && !isNaN(arg);
          if (typeof arg === 'string') {
            const lowerStr = arg.toLowerCase().trim();
            return !(lowerStr === 'false' || lowerStr === '0' || lowerStr === '' || lowerStr === 'null' || lowerStr === 'undefined');
          }
          return Boolean(arg);
        });
      },

      /**
       * OR逻辑或运算
       * @param {...boolean} args - 多个条件表达式
       * @returns {boolean} 任意条件为真时返回true
       */
      OR: (...args) => {
        return args.some(arg => {
          if (typeof arg === 'boolean') return arg;
          if (typeof arg === 'number') return arg !== 0 && !isNaN(arg);
          if (typeof arg === 'string') {
            const lowerStr = arg.toLowerCase().trim();
            return !(lowerStr === 'false' || lowerStr === '0' || lowerStr === '' || lowerStr === 'null' || lowerStr === 'undefined');
          }
          return Boolean(arg);
        });
      },

      /**
       * NOT逻辑非运算
       * @param {boolean} value - 要取反的值
       * @returns {boolean} 取反后的布尔值
       */
      NOT: (value) => {
          if (typeof value === 'boolean') return !value;
          if (typeof value === 'number') return value === 0 || isNaN(value);
          if (typeof value === 'string') {
            const lowerStr = value.toLowerCase().trim();
            return lowerStr === 'false' || lowerStr === '0' || lowerStr === '' || lowerStr === 'null' || lowerStr === 'undefined';
          }
          return !value;  // 修改这里
        },

      /**
       * 比较两个值是否相等
       * @param {any} a - 第一个值
       * @param {any} b - 第二个值
       * @returns {boolean} 相等返回true
       */
      EQ: (a, b) => {
        // 数值比较
        const numA = Number(a);
        const numB = Number(b);
        if (!isNaN(numA) && !isNaN(numB)) {
          return Math.abs(numA - numB) < 1e-10; // 处理浮点数精度问题
        }
        // 字符串比较
        return String(a) === String(b);
      },

      /**
       * 比较第一个值是否大于第二个值
       * @param {any} a - 第一个值
       * @param {any} b - 第二个值
       * @returns {boolean} a > b 时返回true
       */
      GT: (a, b) => {
        const numA = Number(a);
        const numB = Number(b);
        if (isNaN(numA) || isNaN(numB)) {
          throw new Error('GT函数参数必须是数值');
        }
        return numA > numB;
      },

      /**
       * 比较第一个值是否大于等于第二个值
       * @param {any} a - 第一个值
       * @param {any} b - 第二个值
       * @returns {boolean} a >= b 时返回true
       */
      GTE: (a, b) => {
        const numA = Number(a);
        const numB = Number(b);
        if (isNaN(numA) || isNaN(numB)) {
          throw new Error('GTE函数参数必须是数值');
        }
        return numA >= numB;
      },

      /**
       * 比较第一个值是否小于第二个值
       * @param {any} a - 第一个值
       * @param {any} b - 第二个值
       * @returns {boolean} a < b 时返回true
       */
      LT: (a, b) => {
        const numA = Number(a);
        const numB = Number(b);
        if (isNaN(numA) || isNaN(numB)) {
          throw new Error('LT函数参数必须是数值');
        }
        return numA < numB;
      },

      /**
       * 比较第一个值是否小于等于第二个值
       * @param {any} a - 第一个值
       * @param {any} b - 第二个值
       * @returns {boolean} a <= b 时返回true
       */
      LTE: (a, b) => {
        const numA = Number(a);
        const numB = Number(b);
        if (isNaN(numA) || isNaN(numB)) {
          throw new Error('LTE函数参数必须是数值');
        }
        return numA <= numB;
      },

      // ==================== 条件计算函数 ====================

      /**
       * 条件求和
       * @param {array} range - 数据范围
       * @param {function} condition - 条件函数
       * @returns {number} 满足条件的数值之和
       */
      SUMIF: (range, condition) => {
        if (!Array.isArray(range)) {
          throw new Error('SUMIF第一个参数必须是数组');
        }
        
        let sum = 0;
        for (const item of range) {
          if (this.evaluateCondition(item, condition)) {
            const numValue = Number(item);
            if (!isNaN(numValue)) {
              sum += numValue;
            }
          }
        }
        return sum;
      },

      /**
       * 条件计数
       * @param {array} range - 数据范围
       * @param {function} condition - 条件函数
       * @returns {number} 满足条件的元素个数
       */
      COUNTIF: (range, condition) => {
        if (!Array.isArray(range)) {
          throw new Error('COUNTIF第一个参数必须是数组');
        }
        
        let count = 0;
        for (const item of range) {
          if (this.evaluateCondition(item, condition)) {
            count++;
          }
        }
        return count;
      },

      /**
       * 条件平均值
       * @param {array} range - 数据范围
       * @param {function} condition - 条件函数
       * @returns {number} 满足条件的数值平均值
       */
      AVERAGEIF: (range, condition) => {
        if (!Array.isArray(range)) {
          throw new Error('AVERAGEIF第一个参数必须是数组');
        }
        
        let sum = 0;
        let count = 0;
        for (const item of range) {
          if (this.evaluateCondition(item, condition)) {
            const numValue = Number(item);
            if (!isNaN(numValue)) {
              sum += numValue;
              count++;
            }
          }
        }
        return count > 0 ? sum / count : 0;
      },

      // ==================== 工程检测专用函数 ====================

      /**
       * 计算标准差（总体标准差）
       * @param {...number} args - 要计算标准差的数值
       * @returns {number} 标准差
       */
      STANDARD_DEVIATION: (...args) => {
        const validArgs = args.filter(arg => !isNaN(Number(arg))).map(Number);
        if (validArgs.length === 0) return 0;
        const avg = this.functions.AVG(...validArgs);
        const squareDiffs = validArgs.map(value => Math.pow(value - avg, 2));
        return Math.sqrt(this.functions.AVG(...squareDiffs));
      },
      
      // ==================== 安全函数（避免除零等错误） ====================

      /**
       * 安全除法（避免除零错误）
       * @param {number} a - 被除数
       * @param {number} b - 除数
       * @returns {number} 除法结果，除数为0时返回0
       */
      SAFE_DIV: (a, b) => (Number(b) !== 0 ? Number(a) / Number(b) : 0),

      /**
       * 安全取模（避免除零错误）
       * @param {number} a - 被除数
       * @param {number} b - 除数
       * @returns {number} 取模结果，除数为0时返回0
       */
      SAFE_MOD: (a, b) => (Number(b) !== 0 ? Number(a) % Number(b) : 0),
      
      // ==================== 统计函数 ====================

      /**
       * 统计有效参数个数
       * @param {...any} args - 要统计的参数
       * @returns {number} 非空有效参数的数量
       */
      COUNT: (...args) => args.filter(arg => arg !== undefined && arg !== null && arg !== '').length,

      /**
       * 计算中位数
       * @param {...number} args - 要计算中位数的数值
       * @returns {number} 中位数
       */
      MEDIAN: (...args) => {
        const validArgs = args.filter(arg => !isNaN(Number(arg))).map(Number).sort((a, b) => a - b);
        const mid = Math.floor(validArgs.length / 2);
        return validArgs.length % 2 !== 0 ? validArgs[mid] : (validArgs[mid - 1] + validArgs[mid]) / 2;
      },

      // ==================== 字符串函数 ====================

      /**
       * 字符串连接
       * @param {...any} args - 要连接的参数
       * @returns {string} 连接后的字符串
       */
      CONCAT: (...args) => {
        return args.map(arg => String(arg)).join('');
      },

      /**
       * 带分隔符的字符串连接
       * @param {string} separator - 分隔符
       * @param {...any} args - 要连接的参数
       * @returns {string} 连接后的字符串
       */
      CONCAT_WS: (separator, ...args) => {
        return args.map(arg => String(arg)).join(separator);
      }
    };
  }

  /**
   * 评估条件表达式
   * @param {any} value - 要评估的值
   * @param {string|function} condition - 条件表达式或函数
   * @returns {boolean} 是否满足条件
   */
  evaluateCondition(value, condition) {
    if (typeof condition === 'function') {
      return condition(value);
    }
    
    if (typeof condition === 'string') {
      // 解析字符串条件
      const numValue = Number(value);
      const conditionNum = Number(condition.replace(/[<>=!]/g, '').trim());
      
      if (condition.includes('>=')) {
        return numValue >= conditionNum;
      } else if (condition.includes('<=')) {
        return numValue <= conditionNum;
      } else if (condition.includes('>')) {
        return numValue > conditionNum;
      } else if (condition.includes('<')) {
        return numValue < conditionNum;
      } else if (condition.includes('!=')) {
        return numValue !== conditionNum;
      } else if (condition.includes('==')) {
        return numValue === conditionNum;
      } else if (condition.includes('=')) {
        return numValue === conditionNum;
      } else {
        // 默认等于比较
        return String(value) === condition;
      }
    }
    
    return Boolean(value) === Boolean(condition);
  }

  /**
 * 预处理数据，确保数值类型 - 增强版本
 * @param {Object} data 原始数据
 * @returns {Object} 处理后的数据
 */
preprocessData(data) {
  const processed = {}
  
  console.log('[预处理数据] 原始数据:', JSON.stringify(data, null, 2))
  
  Object.keys(data).forEach(key => {
    let value = data[key]
    
    console.log(`[处理参数] ${key}:`, value, '类型:', typeof value, '是否为数组:', Array.isArray(value))
    
    // 处理空值或未定义
    if (value === undefined || value === null) {
      processed[key] = 0
      console.log(`[空值处理] ${key} -> 0`)
      return
    }
    
    // 处理多测次参数数组
    if (Array.isArray(value)) {
      const measureValues = value.map((item, index) => {
        // 如果是对象格式，提取 value 属性
        if (item && typeof item === 'object' && 'value' in item) {
          const numValue = Number(item.value)
          console.log(`[数组元素处理] ${key}[${index}] 对象值:`, item.value, '->', isNaN(numValue) ? 0 : numValue)
          return isNaN(numValue) ? 0 : numValue
        }
        // 如果是直接数值
        const numValue = Number(item)
        console.log(`[数组元素处理] ${key}[${index}] 直接值:`, item, '->', isNaN(numValue) ? 0 : numValue)
        return isNaN(numValue) ? 0 : numValue
      })
      processed[key] = measureValues
      console.log(`[多测次预处理完成] ${key}:`, measureValues)
      return
    }
    
    // 处理单个参数对象（非数组）
    if (typeof value === 'object' && value !== null) {
      console.log(`[对象参数处理] ${key}:`, value)
      if ('value' in value) {
        value = value.value
        console.log(`[对象提取value] ${key} ->`, value)
      }
    }
    
    // 转换为数值（如果可以）
    if (value !== '' && value !== null && value !== undefined) {
      const numValue = Number(value)
      processed[key] = isNaN(numValue) ? value : numValue
    } else {
      processed[key] = 0
    }
    
    console.log(`[普通预处理完成] ${key}: ${processed[key]}`)
  })
  
  console.log('[预处理数据完成] 结果:', JSON.stringify(processed, null, 2))
  return processed
}

   /**
   * 处理多测次参数表达式（支持普通表格多测次参数）
   * @param {string} expression 原始表达式
   * @param {Object} data 数据对象
   * @returns {string} 处理后的表达式
   */
  processMultiMeasureExpression(expression, data) {
    let processedExpr = expression
    if (!expression) return expression
    
    // 匹配多测次参数访问格式：paramCode[index].value 或 paramCode[index]
    const multiMeasurePattern = /(\w+)\[(\d+)\](?:\.value)?/g
    let match
    
    while ((match = multiMeasurePattern.exec(expression)) !== null) {
      const [fullMatch, paramCode, index] = match
      const arrayIndex = parseInt(index)
      
      // 支持两种数据格式：直接数组（普通表格）和对象数组（动态表格）
      if (data[paramCode]) {
        if (Array.isArray(data[paramCode])) {
          // 普通表格：数据是直接的数值数组
          if (arrayIndex >= 0 && arrayIndex < data[paramCode].length) {
            const value = data[paramCode][arrayIndex]
            processedExpr = processedExpr.replace(fullMatch, value.toString())
            console.log(`[多测次替换] ${fullMatch} -> ${value}`)
          } else {
            processedExpr = processedExpr.replace(fullMatch, '0')
            console.warn(`[多测次警告] 索引${arrayIndex}超出范围，参数${paramCode}长度${data[paramCode].length}`)
          }
        } else if (typeof data[paramCode] === 'object' && data[paramCode].value) {
          // 动态表格：数据是对象格式
          const value = data[paramCode].value[arrayIndex] || 0
          processedExpr = processedExpr.replace(fullMatch, value.toString())
          console.log(`[动态表格替换] ${fullMatch} -> ${value}`)
        } else {
          processedExpr = processedExpr.replace(fullMatch, '0')
          console.warn(`[多测次警告] 参数${paramCode}格式不支持`)
        }
      } else {
        processedExpr = processedExpr.replace(fullMatch, '0')
        console.warn(`[多测次警告] 参数${paramCode}不存在`)
      }
    }
    
    return processedExpr
  }

/**
 * 执行计算 - 增强调试版本
 * @param {string} expression 计算表达式
 * @param {Object} data 数据对象
 * @param {Object} options 选项
 * @returns {any} 计算结果
 */
calculate(expression, data = {}, options = {}) {
  try {
    console.log('=== [计算开始] ===')
    console.log('[原始表达式]', expression)
    console.log('[原始数据]', JSON.stringify(data, null, 2))
    console.log('[选项]', options)
    
    // 预处理数据，确保数值类型
    const processedData = this.preprocessData(data)
    
    // 处理多测次参数访问
    let processedExpr = this.processMultiMeasureExpression(expression, processedData)

    console.log('[计算准备完成]', {
      原始表达式: expression,
      处理后的表达式: processedExpr,
      处理后的数据: processedData
    })

    // 构建执行环境
    const env = {
      ...this.functions,
      ...processedData
    }

    console.log('[执行环境] 可用函数:', Object.keys(this.functions))
    console.log('[执行环境] 可用变量:', Object.keys(processedData))

    // 执行计算
    const func = new Function(...Object.keys(env), `return ${processedExpr}`)
    let result = func(...Object.values(env))

    console.log('[计算原始结果]', result, '类型:', typeof result)

    // 处理精度（仅对数字类型）
    if (options.precision !== undefined && typeof result === 'number') {
      result = this.functions.ROUND(result, options.precision)
      console.log('[精度处理] 结果:', result)
    }

    // 验证计算结果
    const finalResult = this.validateResult(result, expression)
    
    console.log('[计算最终结果]', finalResult)
    console.log('=== [计算结束] ===')
    return finalResult
    
  } catch (error) {
    console.error('计算执行失败:', error)
    console.error('错误堆栈:', error.stack)
    throw new Error(`计算失败: ${error.message}`)
  }
}


  /**
   * 验证计算结果
   * @param {any} result 计算结果
   * @param {string} expression 原始表达式
   * @returns {any} 验证后的结果
   */
  validateResult(result, expression) {
    if (result === undefined || result === null) {
      throw new Error('计算结果为 undefined 或 null');
    }
    
    if (typeof result === 'number') {
      if (isNaN(result)) {
        throw new Error('计算结果为 NaN');
      }
      
      if (!isFinite(result)) {
        // 检查是否除零
        if (expression.includes('/') && result === Infinity) {
          throw new Error('计算过程中出现除零错误');
        }
        throw new Error('计算结果为无限值');
      }
    }
    
    return result;
  }

  /**
   * 验证表达式语法
   * @param {string} expression 计算表达式
   * @param {Array} dependencies 依赖参数列表
   * @param {Array} multiMeasureDeps 多测次依赖参数
   * @returns {Object} 验证结果
   */
  validateExpression(expression, dependencies = [], multiMeasureDeps = []) {
    if (!expression || !expression.trim()) {
      return { valid: false, message: '表达式不能为空' };
    }

    try {
      // 1. 替换多测次参数访问格式
      let testExpression = this.replaceMultiMeasureAccess(expression, multiMeasureDeps);
      
      // 2. 替换普通参数为测试值
      dependencies.forEach(depCode => {
        const regex = new RegExp(`\\b${depCode}\\b`, 'g');
        testExpression = testExpression.replace(regex, '100');
      });

      // 3. 构建安全执行环境
      const safeEnv = { ...this.functions };
      
      // 4. 验证表达式语法
      const testFn = new Function(...Object.keys(safeEnv), `return ${testExpression}`);
      const result = testFn(...Object.values(safeEnv));

      // 5. 检查结果是否为有效数字或布尔值
      if (typeof result !== 'number' && typeof result !== 'boolean' && typeof result !== 'string') {
        return { valid: false, message: '表达式计算结果必须是数字、布尔值或字符串' };
      }

      if (typeof result === 'number' && (isNaN(result) || !isFinite(result))) {
        return { valid: false, message: '表达式计算结果不是有效数字' };
      }

      return { 
        valid: true, 
        message: `表达式验证通过！测试计算结果：${result}`,
        testResult: result 
      };
    } catch (error) {
      console.error('表达式验证失败:', error);
      return { 
        valid: false, 
        message: `表达式语法错误：${this.formatError(error.message)}` 
      };
    }
  }

  /**
   * 替换多测次参数访问格式
   * @param {string} expression 原始表达式
   * @param {Array} multiMeasureDeps 多测次依赖参数
   * @returns {string} 替换后的表达式
   */
  replaceMultiMeasureAccess(expression, multiMeasureDeps) {
    let result = expression;
    
    multiMeasureDeps.forEach(param => {
      // 匹配 paramCode[index].value 格式
      const pattern = new RegExp(`\\b${param.paramCode}\\[(\\d+)\\]\\.value\\b`, 'g');
      result = result.replace(pattern, '100'); // 替换为测试值
    });
    
    return result;
  }

  /**
   * 格式化错误信息
   * @param {string} errorMessage 原始错误信息
   * @returns {string} 格式化后的错误信息
   */
  formatError(errorMessage) {
    const errorMap = {
      'Unexpected token': '存在未预期的符号',
      'is not defined': '存在未定义的变量或函数',
      'Missing )': '缺少右括号',
      'Invalid left-hand side': '无效的左操作数',
      'Unexpected end of input': '表达式不完整'
    };

    for (const [key, value] of Object.entries(errorMap)) {
      if (errorMessage.includes(key)) {
        return value;
      }
    }

    return errorMessage;
  }

  /**
   * 验证配置完整性
   * @param {Object} config 配置对象
   * @returns {Array} 错误信息列表
   */
  validateConfig(config) {
    const errors = [];

    // 基础信息验证
    if (!config.projectName?.trim()) {
      errors.push('检测项目名称不能为空');
    }

    if (!config.projectId?.trim()) {
      errors.push('项目编码不能为空');
    }

    if (!config.standardCode?.trim()) {
      errors.push('执行标准不能为空');
    }

    // 参数组验证
    if (!config.paramGroups || config.paramGroups.length === 0) {
      errors.push('至少需要配置一个参数组');
    }

    // 参数编码唯一性验证
    const paramCodes = new Set();
    this.traverseAllParams(config, (param) => {
      if (!param.paramCode?.trim()) {
        errors.push(`参数"${param.paramName}"缺少参数编码`);
        return;
      }

      if (paramCodes.has(param.paramCode)) {
        errors.push(`参数编码"${param.paramCode}"重复（参数：${param.paramName}）`);
      }
      paramCodes.add(param.paramCode);

      // 计算参数验证
      if (param.paramType === 'calculation') {
        if (!param.calculationExpr?.trim()) {
          errors.push(`计算参数"${param.paramName}"缺少计算表达式`);
        }

        if (!param.dependencies || param.dependencies.length === 0) {
          errors.push(`计算参数"${param.paramName}"未配置依赖参数`);
        }

        // 验证依赖参数是否存在
        if (param.dependencies) {
          param.dependencies.forEach(depCode => {
            if (!paramCodes.has(depCode)) {
              errors.push(`计算参数"${param.paramName}"的依赖参数"${depCode}"不存在`);
            }
          });
        }
      }

      // 下拉选项验证
      if (param.dataType === 'select' && (!param.options || param.options.length === 0)) {
        errors.push(`下拉参数"${param.paramName}"未配置选项`);
      }

      // 数字精度验证
      if (param.dataType === 'number' && (param.precision === undefined || param.precision < 0)) {
        errors.push(`数字参数"${param.paramName}"的数字精度配置无效`);
      }
    });

    return errors;
  }

  /**
   * 遍历所有参数
   * @param {Object} config 配置对象
   * @param {Function} callback 回调函数
   */
  traverseAllParams(config, callback) {
    if (!config.paramGroups) return;

    config.paramGroups.forEach((group, groupIndex) => {
      const groupPath = `参数组[${groupIndex}] "${group.groupName}"`;
      
      if (group.isNested && group.childGroups) {
        group.childGroups.forEach((childGroup, childIndex) => {
          const childPath = `${groupPath} -> 子组[${childIndex}] "${childGroup.groupName}"`;
          childGroup.paramItems?.forEach((param, paramIndex) => {
            callback(param, `${childPath} -> 参数[${paramIndex}]`);
          });
        });
      } else {
        group.paramItems?.forEach((param, paramIndex) => {
          callback(param, `${groupPath} -> 参数[${paramIndex}]`);
        });
      }
    });
  }
}

export default FormulaCalculator;